<template>
  <div style="height: 100%; overflow: auto; padding: 20px">
    <fm-generate-form
      :data="JSON.parse(controlData.designData)"
      :remote="remoteFuncs"
      v-model="models"
      :pageAction="pageAction"
      ref="smartform"
      :objectKey="objectKey"
      v-if="!pageLoading"
      @loaded="loadDone"
    >
      <template v-slot:inner>
        <div v-html="vHtml"></div>
      </template>
    </fm-generate-form>

    <vxe-modal
      class="qm-workflow-process-img"
      ref="imgModal"
      v-model="imgModalVisible"
      resize
      show-zoom
      width="900px"
      height="500px"
      title="流程图"
    >
      <img v-if="imgModalVisible" :src="imgUrl" />
    </vxe-modal>

    <qm-workflow-select-user
      v-model="selectUserVisible"
      :url="selectUserUrl"
      :params="models"
      :pageAction="pageAction"
      :needChoose="controlData.workflow.needChoose"
      @select-done="doSend"
      @cancel="selectUserVisible = false"
    ></qm-workflow-select-user>

    <qm-workflow-jump
      v-model="selectJumpVisible"
      :url="selectJumpUrl"
      :params="models"
      :pageAction="pageAction"
      @select-done="doProcessJump"
      @cancel="selectJumpVisible = false"
    ></qm-workflow-jump>

    <common-select
      v-model="selectUserNotify"
      selectKey="selectUsers"
      selectMode="1"
      @success="doProcessDoNotify"
    ></common-select>

    <iframe ref="smartform_jsframe" name="smartform_jsframe" v-show="false"></iframe>
  </div>
</template>

<script>
import controller from "@/libs/framework/workflowController";
import Injection from "@/libs/framework/injection";
import _ from "lodash";
import QmWorkflowSelectUser from "@/libs/components/qm-workflow-select-user";
import QmWorkflowJump from "@/libs/components/qm-workflow-jump";
import LoaderProxy from "@/libs/framework/loaderProxy";
import user from "@/store/modules/user";
import CommonSelect from "@/views/commonSelect/list";
import { smartformDB, queryOne, del, add } from "@/utils/dexie.js";
import request from "@/utils/request";

var qs = require("qs");

export default class instance extends controller {
  onBeforeInit() {
    this.urls = {
      model: "/workflow/mobile/jump",
    };
  }

  onInit() {
    // let pageCode = this.vm.pageCode || this.$params.pageCode;
    // if (pageCode && pageCode.indexOf("?") != -1) {
    //   let p = qs.parse(pageCode.substr(pageCode.indexOf("?") + 1));
    //   this.vm.qsObject = p || {};
    // }

    let pageCode = this.$params.pageCode || this.vm.pageCode;
    let taskId = this.$params.taskId || this.vm.taskId;
    let assigneeId = this.$params.assigneeId || this.vm.assigneeId;
    let historyTaskId = this.$params.historyTaskId || this.vm.historyTaskId;
    let version = this.$params.version || this.vm.version;
    let appCode = this.$params.appCode || this.vm.appCode;
    let formId = this.$params.formId || this.vm.formId;

    this.setRequestParam("pageCode", pageCode, "form");
    this.setRequestParam("taskId", taskId, "form");
    this.setRequestParam("assigneeId", assigneeId, "form");
    this.setRequestParam("historyTaskId", historyTaskId, "form");
    this.setRequestParam("version", version, "form");
    this.setRequestParam("appCode", appCode, "form");
    this.setRequestParam("formId", formId, "form");

    if (!taskId && !historyTaskId && !formId) {
      let url = `/smartform/mobile/hub/${pageCode}`;
      this.urls.model = url;
    }
  }

  async getViewModel(conditions, preloader = false) {
    let pageCode = this.vm.pageCode || this.$params.pageCode;
    this.context.pageLoading = true;
    let loading;
    if (preloader) {
      loading = this.vm.appLoading("数据加载中...");
    }

    /**
     * 部分数据由前端进行缓存(cssCode、designData、jsCode、watchProp)
     * 以hasFrontEndCache用于区分是否需要查询缓存数据
     */
    // cacheKey为userId&pageCode
    const isCache = process.env.VUE_APP_SMARTFORM_CACHE === true;
    if (isCache) {
      const cacheKey = user.state.userId + "&" + pageCode;
      const cacheData = await queryOne(
        smartformDB,
        "smartformCacheTable",
        "cacheKey",
        cacheKey
      );
      if (!cacheData) {
        this.setRequestParam("hasFrontEndCache", false, "form");
      } else {
        const { cacheCreateTime } = cacheData;
        // cacheCreateTime无效，或者已过期
        if (
          cacheCreateTime == null ||
          parseInt(
            (new Date().getTime() - cacheCreateTime) / 1000 / (60 * 60)
          ) > 24
        ) {
          this.setRequestParam("hasFrontEndCache", false, "form");
          await del(smartformDB, "smartformCacheTable", "cacheKey", cacheKey);
        } else {
          this.setRequestParam("hasFrontEndCache", true, "form");
        }
      }
    } else {
      this.setRequestParam("hasFrontEndCache", false, "form");
    }
    return new Promise((resolve, reject) => {
      new LoaderProxy(this, conditions).load(resolve, reject, preloader);
    })
      .then(() => {
        this.context.pageLoading = false;
        if (preloader) {
          loading.close();
        }
      })
      .catch(() => {
        this.context.pageLoading = false;
        if (preloader) {
          loading.close();
        }
      });
  }

  async onAfterQuery(type, isSuccess, result) {
    if (isSuccess) {
      if (result.pageAction == "create") {
        result.pageActionText = "发起";
        result.controlData.title += result.controlData.title.endsWith("申请")
          ? ""
          : "申请";
      } else if (result.pageAction == "edit") {
        result.pageActionText = "";
        result.controlData.title += result.controlData.title.endsWith("审批")
          ? ""
          : "审批";
      }
      // if (result.enums) {
      //   this.vm.$root.enums = result.enums;
      // }
      // if (result.dicts) {
      //   this.vm.$root.dicts = result.dicts;
      // }
      // if (result.controlData) {
      //   this.vm.$root.controlData = result.controlData;
      // }
      // if (result.primaryKey) {
      //   this.vm.$root.primaryKey = result.primaryKey;
      // }
      if (result.primaryKey) {
        result.primaryKey["storeId"] = result.models.model["storeId"];
      }
      if (result.models && result.models.model) {
        let datakey = result.models.model["datakey"];
        result.models.model["datakey"] = datakey || Math.uuid();
      }

      const isCache = process.env.VUE_APP_SMARTFORM_CACHE === true;
      if (isCache) {
        const { cssCode, designData, jsCode, watchProp } = result.controlData;
        const { formCode } = result.models.model;
        // cacheKey为userId&formCode
        const cacheKey = user.state.userId + "&" + formCode;
        const cacheData = await queryOne(
          smartformDB,
          "smartformCacheTable",
          "cacheKey",
          cacheKey
        );
        if (cacheData) {
          const { cssCode, designData, jsCode, watchProp } = cacheData;
          Object.assign(result.controlData, {
            cssCode: cssCode,
            designData: designData,
            jsCode: jsCode,
            watchProp: watchProp,
          });
        } else {
          await add(smartformDB, "smartformCacheTable", {
            cacheKey: cacheKey,
            cacheCreateTime: new Date(),
            cssCode: cssCode,
            designData: designData,
            jsCode: jsCode,
            watchProp: watchProp,
          });
        }
      }
    }

    this.vm.loadJs(result);
    this.vm.loadVueMethod(result);

    return result;
  }

  onBeforeSave(postModel) {
    return !(this.vm.onBeforeSave && this.vm.onBeforeSave(postModel) === false);
  }

  onBeforeSend(postModel) {
    return !(this.vm.onBeforeSend && this.vm.onBeforeSend(postModel) === false);
  }
  onAfterSend(isSuccess, result) {
    this.vm.onAfterSend && this.vm.onAfterSend(isSuccess, result);
  }

  onAfterSave(isSuccess, result) {
    this.vm.onAfterSave && this.vm.onAfterSave(isSuccess, result);
  }

  mixin() {
    return {
      components: {
        QmWorkflowSelectUser,
        QmWorkflowJump,
        CommonSelect,
      },
      props: {
        // 表单相关
        pageId: String,
        pageCode: String,
        version: String | Number,
        // 工作流相关
        appCode: String,
        taskId: String,
        historyTaskId: String,
        assigneeId: String,
        // 主键
        pkey: Object,
      },
      data() {
        return {
          selectUserNotify: false,
          pageLoading: false,
          controlData: {
            workflow: {
              needChoose: false,
            },
            formTables: [],
            tableColumns: [],
            tables: [],
            designData: `{
              "list": [],
              "f7list": [],
              "config": {
                "labelWidth": 100,
                "labelPosition": "right",
                "size": "small",
                "customClass": "",
                "ui": "element",
                "layout": "horizontal",
                "labelCol": 3
              },
              "page": {
                "pageId": "",
                "title": "",
                "onVueCreated": "",
                "onVueMounted": ""
              },
              "f7page": {
                "pageContent": true,
                "hideNavbarOnScroll": false,
                "hideToolbarOnScroll": false,
                "ptr": true,
                "infinite": true,
                "onVueCreated": "",
                "onVueMounted": ""
              }
            }`,
          },
          primaryKey: {},
          pageAction: "create",
          jsonData: {},
          editData: {},
          remoteFuncs: {},
          formName: "smartform",
          enums: {},
          dicts: {},
          models: {
            model: {},
          },
          urls: {},
          vHtml: "",
          imgModalVisible: false,
          imgUrl: "",
          selectUserVisible: false,
          selectUserUrl: "",
          selectJumpUrl: "",
          objectKey: "",
          qsObject: {},
          selectJumpVisible: false,
        };
      },

      methods: {
        appendWorkflowArgs(url) {
          let args = {
            appCode: this.controlData.workflow.appCode,
            version: this.controlData.workflow.version,
            taskId: this.controlData.workflow.taskId,
            instanceId: this.controlData.workflow.taskId,
            assigneeId: this.controlData.workflow.assigneeId,
            pageAction: this.pageAction,
          };
          for (let o in args) {
            if (!args[o]) continue;
            let joinChar = url.indexOf("?") == -1 ? "?" : "&";
            url += joinChar;
            url += o + "=" + args[o];
          }
          return url;
        },
        getData() {
          return this.$refs.smartform.getData();
        },
        saveThenReload() {
          // let self = this;
          // let loading = self.notifyInfo("数据加载中");
          // let storeId = self.models.model.storeId;
          // let pageCode = self.models.model.formCode;
          // let url = `/smartform/mobile/hub/${pageCode}`;
          // self.super.urls.model = url;
          // self.getViewModel({ storeId: storeId, pageAction: 'edit' }).then(() => {
          //   loading.close();
          // });
        },
        loadVueMethod(result) {
          let vueMethod = {};
          let frameWindow = this.$refs.smartform_jsframe.contentWindow;

          if (
            result &&
            result.controlData &&
            result.controlData.vueMethod &&
            frameWindow
          ) {
            let vMetText = result.controlData.vueMethod;
            if (!vMetText.startsWith("{")) {
              vMetText = "{" + vMetText + "}";
            }

            vueMethod = JSON.stringify(vMetText, function (key, val) {
              if (typeof val === "function") {
                return val + "";
              }
              return val;
            });
            vueMethod = JSON.parse(vueMethod, function (k, v) {
              if (v.indexOf && v.indexOf("function") > -1) {
                return frameWindow.eval("(function(){return " + v + " })()");
              }
              return v;
            });
          }

          _.each(vueMethod, (value, key) => {
            if (typeof value === "function") {
              this[key] = function () {
                return value(...arguments);
              };
            }
          });
        },
        loadJs(result) {
          result = result || { controlData: {} };
          // 该 htmlClear 方法有问题，希望开发人员写的js不要有XSS风险
          // let js = this.super.$util.htmlClear(result.controlData.jsCode || "");
          let js = result.controlData.jsCode || "";

          let frameWindow = this.$refs.smartform_jsframe.contentWindow;
          if (frameWindow) {
            frameWindow.vue = this;
            frameWindow.data = result;
            Injection.injectSmartformJs(frameWindow);

            const s = frameWindow.document.createElement("script");
            s.type = "text/javascript";
            s.innerHTML = `${js}`;

            frameWindow.document.body.appendChild(s);
          }

          this.objectKey = Math.uuid();
          window[this.objectKey] = frameWindow;
        },
        loadCss() {
          let css = this.super.$util.htmlClear(this.controlData.cssCode || "");
          this.vHtml = `<style> ${css} <\/style>`;
        },
        loadWatchProp() {
          let watchProp = {};
          let frameWindow = this.$refs.smartform_jsframe.contentWindow;

          if (this.controlData.watchProp && frameWindow) {
            let wpText = this.controlData.watchProp;
            if (!wpText.startsWith("{")) {
              wpText = "{" + wpText + "}";
            }

            watchProp = JSON.stringify(wpText, function (key, val) {
              if (typeof val === "function") {
                return val + "";
              }
              return val;
            });

            watchProp = JSON.parse(watchProp, function (k, v) {
              if (v.indexOf && v.indexOf("function") > -1) {
                return frameWindow.eval("(function(){return " + v + " })()");
              }
              return v;
            });
          }

          let self = this;

          _.each(watchProp, (value, key) => {
            this.$watch(key, function (newVal, oldVal) {
              if (typeof value === "function") {
                value(newVal, oldVal, self);
              }
            });
          });
        },
        loadDone() {
          this.loadCss();
          this.loadWatchProp();

          let $smartform = this.$refs["smartform"];
          // if (
          //   $smartform.data.page.onVueCreated &&
          //   this.$root[$smartform.data.page.onVueCreated]
          // ) {
          //   this.$root[$smartform.data.page.onVueCreated](
          //     $smartform.$refs["elementGenerateForm"]
          //   );
          // }

          // if (
          //   $smartform.data.page.onVueMounted &&
          //   this.$root[$smartform.data.page.onVueMounted]
          // ) {
          //   this.$root[$smartform.data.page.onVueMounted](
          //     $smartform.$refs["elementGenerateForm"]
          //   );
          // }

          if (this.pageAction === "view") {
            $smartform.disabled("all", true);
          }
        },

        doSend({ choices, selectComment, sendComment }) {
          if (this.controlData.workflow.needChoose) {
            if (choices.length == 0) {
              this.$message.warning("请选择处理人！");
              return;
            }
            if (choices.length > 1) {
              this.$message.warning("只能选择一个处理环节！");
              return;
            }
          }
          if (!sendComment) {
            this.$message.warning("请填写处理意见！");
            return;
          }

          let postModel = this.models;
          postModel.pageAction = this.pageAction;
          postModel.workflowComment = sendComment;
          if (
            choices &&
            choices.length &&
            this.controlData.workflow.needChoose
          ) {
            postModel.choice = choices[0];
          }

          this.super.processSave(this.models, undefined, true).then((r) => {
            this.selectUserVisible = false;
          });
        },
        done() {
          window.setTimeout(() => {
            this.$root.closeModal();
            //window.location.href = window.location.href;
          }, 3000);
        },

        getModels() {
          return this.$refs.smartform.models;
        },

        close() {
          this.$root.closeModal();
        },

        appendPrimaryKey(url, model) {
          if (!model) return url;
          for (let o in model) {
            let joinChar = url.indexOf("?") == -1 ? "?" : "&";
            url += joinChar;
            url += o + "=" + encodeURI(model[o] || "");
          }
          return url;
        },

        processSave() {
          this.$refs.smartform
            .getData()
            .then((d) => {
              let isNew = this.pageAction === "create";
              this.super.processSave(undefined, undefined, false).then((r) => {
                if (isNew) {
                  this.saveThenReload();
                }
              });
            })
            .catch((e) => {
              this.notifyError("表单校验不通过，请填写相关信息");
            });
        },
        processSend() {
          this.$refs.smartform
            .getData()
            .then((d) => {
              if (
                this.controlData.workflow.needChoose ||
                !this.controlData.workflow.isFirstTask ||
                this.controlData.isNoChooseNeedComment
              ) {
                this.selectUserUrl = this.appendWorkflowArgs(
                  this.urls.selectUser
                );
                this.selectUserVisible = true;
              } else {
                this.super.processSave(undefined, undefined, true);
              }
            })
            .catch((e) => {
              this.notifyError("表单校验不通过，请填写相关信息");
            });
        },
        processDoNotify(users = []) {
          this.selectUserNotify = true;
        },
        doProcessDoNotify(users = []) {
          this.super.processDoNotify(users);
        },
        processNotify() {
          this.super.processNotify();
        },
        processRollback() {
          this.super.processRollback().then((r) => {
            this.done();
          });
        },
        processBackward() {
          this.processJump();
          // this.super.processBackward().then((r) => {
          //   this.done();
          // });
        },
        processDelete() {
          this.super.processDelete().then((r) => {
            this.done();
          });
        },
        processTerminate() {
          this.super.processTerminate().then((r) => {
            this.done();
          });
        },
        processTrace() {
          this.processGuide();
          // let instanceId = this.controlData.workflow.instanceId || "";
          // let appCode = this.controlData.workflow.appCode;
          // let url = this.urls.processTrace;
          // url = url + "?appCode=" + appCode + "&instanceId=" + instanceId;
          // this.imgUrl = `${process.env.VUE_APP_BASE_API}${url}`;
          // this.imgModalVisible = true;
        },
        processTrace2() {
          let instanceId = this.controlData.workflow.instanceId || "";
          let appCode = this.controlData.workflow.appCode;
          let url = this.urls.processTrace;
          url = url + "?appCode=" + appCode + "&instanceId=" + instanceId;
          this.imgUrl = `${process.env.VUE_APP_BASE_API}${url}`;
          this.imgModalVisible = true;
        },
        processGuide() {
          request
            .post("/workflow/serviceGuide/getEntityByCode", {
              code: this.models.model.formCode,
              pageAction: "view",
            })
            .then((r) => {
              if (!r || r.initMessage) {
                this.processTrace2();
                // this.$alert(
                //   `未配置编码为“${this.models.model.formCode}”的办事指南`
                // );
              } else {
                this.$root.openModal(
                  "/workflow/serviceGuide/view",
                  {
                    workflow: this.controlData.workflow,
                    viewModel: r,
                    models: r.models,
                  },
                  "85%",
                  "90%",
                  { title: "流程指南" }
                );
              }
            });
        },
        processJump() {
          this.selectJumpUrl = this.appendWorkflowArgs(this.urls.selectJump);
          this.selectJumpVisible = true;
        },
        doProcessJump(parmas) {
          this.super.processJump(parmas).then((r) => {
            this.done();
          });
        },
      },
      mounted() {
        this.$once("hook:beforeDestroy", () => {
          if (this.objectKey) {
            window[this.objectKey] = null;
          }
        });
      },
      activated() {
        this.loadJs(this.$data);
        this.loadVueMethod(this.$data);
      },
    };
  }
}
</script>

<style scoped>
</style>
